<?php
/**
 * 函数库
 * @author nengzhi
 * 2015-07-15
 * UTF-8
 */
class Lib_Function{

	private static $obj = null;
	private $charset="abcdefghzkmnpqrstuvwxyABCDEFGHZKMNPQRSTUVWXY23456789"; //随机因子
	private function __construct(){}

	/**
	 * 获取单例对象
	 * @param string $hl
	 * @param number $timeout
	 * @return TyLib_Function
	 */
	public static function getInstance(){
		if(is_null(self::$obj)){
			self::$obj = new Lib_Function();
		}

		return self::$obj;
	}

	/**
	 * 二维数组排序
	 * @param type $multi_array
	 * @param type $sort_key
	 * @param type $sort
	 * @return boolean
	 */
	public function multi_array_sort($multi_array,$sort_key,$sort=SORT_DESC){

	    if(!is_array($multi_array)){
			return false;
		}
		$key_array = array();
		foreach ($multi_array as $row_array){
			if(!is_array($row_array)){
				return false;
			}
			$key_array[] = $row_array[$sort_key];
		}
		array_multisort($key_array,$sort,$multi_array);
		return $multi_array;
	}

	/**
	 * 数据转码
	 * @param unknown $str
	 * @param unknown $code 目标编码
	 * @return unknown
	 */
	public function conversion_coding($str, $code){
		$encode = mb_detect_encoding($str, array('UTF-8','GBK','GB2312','BIG5','ASCII'));
		if($encode == $code or !$encode){
			return $str;
		}
		if(!is_string($str)){
			return $str;
		}
		if($encode === 'GB2312' or $encode === 'GBK'){
			$encode = $encode . '//IGNORE';
		}
		return iconv($encode, $code, $str);
	}



	/**
	 * curl全局封装方法
	 * @param unknown $url
	 * @param number $limit
	 * @param string $post
	 * @param string $cookie
	 * @param string $bysocket
	 * @param string $ip  C端IP地址传输到B端
	 * @param number $timeout
	 * @param string $block
	 * @param string $encodetype
	 * @param string $allowcurl
	 */
	public function dfopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 3, $block = TRUE, $encodetype  = 'URLENCODE', $allowcurl = TRUE) {
		$return = '';
		$matches = parse_url($url);
		$scheme = $matches['scheme'];
		$host = $matches['host'];
		$path = $matches['path'] ? $matches['path'].(isset($matches['query']) && $matches['query'] ? '?'.$matches['query'] : '') : '/';
		$port = !empty($matches['port']) ? $matches['port'] : ($scheme == 'https' ? 443 : 80);
		if(function_exists('curl_init') && $allowcurl) {
			$ch = curl_init();
            if($ip){
                curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: ".$host, 'CLIENT-IP:'.$ip));
            }else{
                curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: ".$host));
            }
            curl_setopt($ch, CURLOPT_URL, $scheme.'://'.$host.':'.$port.$path);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  // 从证书中检查SSL加密算法是否存在
            //curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
            if($post) {
				curl_setopt($ch, CURLOPT_POST, 1);
				if($encodetype == 'URLENCODE') {
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
				} else {
					parse_str($post, $postarray);
					curl_setopt($ch, CURLOPT_POSTFIELDS, $postarray);
				}
			}

			if($cookie) {
				curl_setopt($ch, CURLOPT_COOKIE, $cookie);
			}
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
			$data = curl_exec($ch);
			$status = curl_getinfo($ch);
			$errno = curl_errno($ch);
			curl_close($ch);
			if($errno || $status['http_code'] != 200) {
				$status['code'] = 503;
				return json_encode($status);
			}
			return !$limit ? $data : substr($data, 0, $limit);
		}

		if($post) {
			$out = "POST $path HTTP/1.0\r\n";
			$header = "Accept: */*\r\n";
			$header .= "Accept-Language: zh-cn\r\n";
			$boundary = $encodetype == 'URLENCODE' ? '' : '; boundary='.trim(substr(trim($post), 2, strpos(trim($post), "\n") - 2));
			$header .= $encodetype == 'URLENCODE' ? "Content-Type: application/x-www-form-urlencoded\r\n" : "Content-Type: multipart/form-data$boundary\r\n";
			$header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
			$header .= "Host: $host:$port\r\n";
			$header .= 'Content-Length: '.strlen($post)."\r\n";
			$header .= "Connection: Close\r\n";
			$header .= "Cache-Control: no-cache\r\n";
			$header .= "Cookie: $cookie\r\n\r\n";
			$out .= $header.$post;
		} else {
			$out = "GET $path HTTP/1.0\r\n";
			$header = "Accept: */*\r\n";
			$header .= "Accept-Language: zh-cn\r\n";
			$header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
			$header .= "Host: $host:$port\r\n";
			$header .= "Connection: Close\r\n";
			$header .= "Cookie: $cookie\r\n\r\n";
			$out .= $header;
		}

		$fpflag = 0;
		if(!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout)) {
			$context = array(
					'http' => array(
							'method' => $post ? 'POST' : 'GET',
							'header' => $header,
							'content' => $post,
							'timeout' => $timeout,
					),
			);
			$context = stream_context_create($context);
			$fp = @fopen($scheme.'://'.($ip ? $ip : $host).':'.$port.$path, 'b', false, $context);
			$fpflag = 1;
		}

		if(!$fp) {
			return '';
		}
		stream_set_blocking($fp, $block);
		stream_set_timeout($fp, $timeout);
		@fwrite($fp, $out);
		$status = stream_get_meta_data($fp);
		if(!$status['timed_out']) {
			while (!feof($fp) && !$fpflag) {
				if(($header = @fgets($fp)) && ($header == "\r\n" ||  $header == "\n")) {
					break;
				}
			}

			$stop = false;
			while(!feof($fp) && !$stop) {
				$data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
				$return .= $data;
				if($limit) {
					$limit -= strlen($data);
					$stop = $limit <= 0;
				}
			}
		}
		@fclose($fp);
		return $return;
	}

	public function openCurl($url, $data){ // 模拟提交数据函数
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        $tmpInfo = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Errno'.curl_error($curl);//捕抓异常
        }
        curl_close($curl); // 关闭CURL会话
        return $tmpInfo; // 返回数据，json格式
    }



	/**
	 * 验证手机号码
	 * @param unknown $mobile
	 * @return boolean|unknown
	 */
	public function checkmobile($mobile){
		$rule = '/^1[3|4|5|6|7|8|9][\d]{9}/';
		preg_match($rule, $mobile, $regex);
		if(!$regex[0] || strlen($mobile) > 11){
			return false;
		}
		return $mobile;
	}


	/**
	 * PHP获取当前客户端请求IP地址
	 * @return Ambigous <unknown, mixed>
	 */
    public function getip() {
        $unknown = 'unknown';
        $ip = '';
        if(isset($_SERVER['HTTP_X_CONNECTING_IP']) && trim($_SERVER['HTTP_X_CONNECTING_IP']) != false){
            $ip = trim($_SERVER['HTTP_X_CONNECTING_IP']);
        }else{
            if(!empty($_SERVER['HTTP_X_REAL_FORWARDED_FOR'])){
                $ip = $_SERVER['HTTP_X_REAL_FORWARDED_FOR'];
            }else{
                if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], $unknown)) {
                    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
                    //处理多层代理的情况
                    if(false !== strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')){
                        if (false !== strpos($ip, ',')) $ip = reset(explode(',', $ip));
                        $ip = trim($ip);
                    }
                }elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], $unknown)){
                    $ip = $_SERVER['REMOTE_ADDR'];
                }
            }
        }
        return $ip;
    }
    public function getIpNew()
    {
        if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } else {
            if ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")) {
                $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            } else {
                if ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")) {
                    $ip = $_SERVER["REMOTE_ADDR"];
                } else {
                    if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],
                            "unknown")
                    ) {
                        $ip = $_SERVER['REMOTE_ADDR'];
                    } else {
                        $ip = "unknown";
                    }
                }
            }
        }
        return ($ip);
    }



    /**
     * @身份证
     */
    public  function Identity($subject) {
		//新加验证
		$value = strtoupper($subject);
		$length = strlen($value);
		//判断位数,只支持18位
		if($length != 18)
		{
			return false;
		}
		//验证是否是数字和X
		$sublength = $length - 1;
		$pattern = '/[0-9]{' . $sublength . '}[0-9X]/';
		$match = preg_match($pattern, $value);
		if(!$match)
		{
			return false;
		}
		//验证加权
		$year = substr($value, 6, 2);
		if($year < 19 || $year > 20)
		{
			return false;
		}
		$w = array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);
		$y = array('1','0','X','9','8','7','6','5','4','3','2');
		$sum = 0;
		for($i = 0; $i < $length - 1; $i++)
		{
			$sum += substr($value, $i, 1) * $w[$i];
		}
		$last = $sum % 11;
		if(substr($value, 17, 1) != $y[$last])
		{
			return false;
		}
		return true;
    }

    //通过输入的身份证，获取得到自己的年龄
    public function getAge($card){
        if(empty($card)) return '';
        //出生年月
        $date=strtotime(substr($card,6,8));
        $today=strtotime('today');
        $diff=floor(($today-$date)/86400/365);
        //得到两个日期相差的大体年数
        //strtotime加上这个年数后得到那日的时间戳后与今日的时间戳相比
        $age=strtotime(substr($card,6,8).' +'.$diff.'years')>$today?($diff+1):$diff;
        return $age;
    }

	//将时间戳转换成时间描述，$show_time为时间戳
	public function tran_timestamp($show_time, $format='Y-m-d'){
		date_default_timezone_set("Asia/Shanghai");   //设置时区
		$now_time = date("Y-m-d H:i:s", time());
		$now_time = strtotime($now_time);
		$dur = $now_time - $show_time;
		if ($dur < 0) {
			return date($format, $show_time);
		} else {
			if ($dur < 60) {
				return $dur . '秒前';
			} else {
				if ($dur < 3600) {
					return floor($dur / 60) . '分钟前';
				} else {
					if ($dur < 86400) {
						return floor($dur / 3600) . '小时前';
					} else {
						return date($format, $show_time);
					}
				}
			}
		}
	}

    //将时间戳转换成时间描述，时：分|月/日|年/月日
    public static function tranDate($time){
        date_default_timezone_set("Asia/Shanghai");   //设置时区
        if(date('Y') != date('Y', $time)){
            return date('Y/m/d', $time);
        }elseif(date('d') != date('d', $time)){
            return date('m/d', $time);
        }else{
            return date('H:i', $time);
        }
    }


    /**
     * 数据转码
     * @param unknown $str
     * @param unknown $code 目标编码
     * @return unknown
     */
    public function conversion_coding_new($str, $code){
        $encode = mb_detect_encoding($str, array('UTF-8','GBK','GB2312','BIG5','ASCII'));
        if($encode == $code or !$encode){
            return $str;
        }
        if(!is_string($str)){
            return $str;
        }
        return mb_convert_encoding($str, $code, $encode);
    }

    function get_ip($field=''){
        $ip = file_get_contents('http://pv.sohu.com/cityjson?ie=utf-8');
        preg_match('/{.+}/i', $ip, $m);

        $array = json_decode($m[0]);
        if(is_object($array)) {
            $array = (array)$array;
        } else if(is_array($array)) {
            foreach($array as $key=>$value) {
                $array[$key] = object_array($value);
            }
        }

        if(!empty($field)) return $array[$field];
        return $array;
    }

    //根据ip获得城市
    function getCity($ip = ''){
        $url="http://ip.taobao.com/service/getIpInfo.php?ip=".$ip;
        $ip=json_decode(file_get_contents($url));
        if((string)$ip->code=='1'){
            $data = array();
            Func_Log::write ("sina",'$ip',var_export($ip,true));
            // 新浪接口请求无返回
//            $url = "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=".$ip;
//            $data=json_decode(file_get_contents($url),true);
//            if(!$data['country'] && !$data['city']){
//                return false;
//            }
        }else{
            $data = (array)$ip->data;
        }
        return $data;
        /*
            $url = "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=".$ip;
            $data=json_decode(file_get_contents($url),true);
            if(!$data['country'] && !$data['city']){
                $url="http://ip.taobao.com/service/getIpInfo.php?ip=".$ip;
                $ip=json_decode(file_get_contents($url));
                if((string)$ip->code=='1'){
                    return false;
                }
                $data = (array)$ip->data;
            }
        return $data;
        */
    }

    /*
     * 校验城市和ip是否一致
     */
    public function checkIpCity($city = [])
    {
        //存在城市信息 直接判断
        $province = isset($_SERVER['HTTP_PROVINCE']) ? urldecode($_SERVER['HTTP_PROVINCE']) : 0;
        if (!empty($province) && in_array($province, $city)) {
            return true;
        }

        //高德接口 判断地理位置
        if (!empty($city)) {
            $clientip = TyLib_Function::getInstance()->getip();
            $cityArr = TyLib_Common::getAddressGaoDeByIp($clientip);
            if (!empty($cityArr['province']) && in_array($cityArr['province'], $city)) {
                return true;
            }
        }
        return false;
    }

    /*
 * 校验城市和ip是否一致
 */
    public function getIpCity($city = [])
    {
        //存在城市信息 直接判断
        $province = isset($_SERVER['HTTP_PROVINCE']) ? urldecode($_SERVER['HTTP_PROVINCE']) : 0;

        if (!empty($province)) {
            return $province;
        } else {
            $clientip = TyLib_Function::getInstance()->getip();
            $cityArr = TyLib_Common::getAddressGaoDeByIp($clientip);
            if (!empty($cityArr['province'])) {
                return $cityArr['province'];
            }
        }
        return false;
    }




    //获取手机归属地
    public function getMobileLocation($mobile = ''){
        $checkMobile = TyLib_Function::getInstance()->checkmobile($mobile);
        if(!$checkMobile) return [];
        $url = "http://cx.shouji.360.cn/phonearea.php?number={$mobile}";
        $data = TyLib_CurlHttp::get($url);
        if (!$data) {
            return [];
        }
        $res = json_decode($data, true);
        if(empty($res) || !is_array($res)){
            return [];
        }
        $resData = isset($res['data']) ? $res['data'] : [];
        if(empty($resData['city'])){
            $resData['city'] = $resData['province'];
        }
        return $resData;
    }


    function get_app_version() {
        $version = $_SERVER['HTTP_USER_AGENT'];
        preg_match('/iOSApp/', $version, $isiOS);
        preg_match('/AndroidApp/', $version, $isAndroid);
        $isiOS = $isiOS ? $isiOS[0] : null;
        $isAndroid = $isAndroid ? $isAndroid[0] : null;
        $arr = array('app_type' => 'unknown','app_version' => 0);
        if ($isiOS) {
            preg_match('/Version[\d.]+/', $version, $app_version);
            $app_version = str_replace('.','',$app_version[0]);
            $app_version =  str_replace('Version','',$app_version);
            $arr['app_type'] = 'iOS';
            $arr['app_version'] = $app_version ? $app_version : 0;
        } else if ($isAndroid) {
            preg_match('/Version([\d.]+)/', $version, $app_version);
            $app_version = str_replace('.','',$app_version[1]);
            $app_version =  str_replace('Version','',$app_version);
            $arr['app_type'] = 'Android';
            $arr['app_version'] = $app_version ? $app_version : 0;
        }
        return $arr;
    }



    function isMobile() {
        // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
            return true;
        }
        // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
        if (isset($_SERVER['HTTP_VIA'])) {
            // 找不到为flase,否则为true
            return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
        }
        // 脑残法，判断手机发送的客户端标志,兼容性有待提高。其中'MicroMessenger'是电脑微信
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $clientkeywords = array('nokia','sony','ericsson','mot','samsung','htc','sgh','lg','sharp','sie-','philips','panasonic','alcatel','lenovo','iphone','ipod','blackberry','meizu','android','netfront','symbian','ucweb','windowsce','palm','operamini','operamobi','openwave','nexusone','cldc','midp','wap','mobile','MicroMessenger');
            // 从HTTP_USER_AGENT中查找手机浏览器的关键字
            if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
                return true;
            }
        }
        // 协议法，因为有可能不准确，放到最后判断
        if (isset ($_SERVER['HTTP_ACCEPT'])) {
            // 如果只支持wml并且不支持html那一定是移动设备
            // 如果支持wml和html但是wml在html之前则是移动设备
            if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
                return true;
            }
        }
        return false;
    }


    /**
     * 返回Json数据
     * @param unknown $code
     * @param array|string|int|bool $data
     * @param string $message
     * @throws Exception
     */
    public function returnJson($code, $data=array(), $message=''){
    	$code = intval($code);
    	if(empty($message)){
    		$message = TyLib_Error::getMsg($code);
    	}

    	$returnData = array(
    			'code'=>$code,
    			'message'=>$message,
    			'data'=>$data
    	);
    	header("Content-type: application/json");
    	echo json_encode($returnData);
    	exit;
    }

	public function httpToHttps($url){

		if(substr_count($url,'http://') > 0){
			$url = str_replace('http://','https://',$url);
		}
		return $url;
	}




    /**
     * 创建目录
     * @param type $dir
     * @param type $mode
     * @return boolean
     */
    public function mk_dir($dir, $mode = 0755){
        if (is_dir($dir) || @mkdir($dir,$mode)){
            return true;
        }
        if (!$this->mk_dir(dirname($dir),$mode)){
            return false;
        }
        return @mkdir($dir,$mode);
    }

    /**
     * 获取随机数根据步长
     * @param $min
     * @param $max
     * @param $step
     * @param $num
     * @param $order
     * @return array|int
     */
    public function getRandNumByStep($min,$max,$step,$num,$order){
        if($step == 1 && $num == 1){
            return mt_rand($min,$max);
        }
        $middle_num = $max/$step;
        $middle_num = is_float($middle_num) ? floor($middle_num) : $middle_num;
        if($num == 1){
            return mt_rand(1,$middle_num)*$step;
        }
        $num_arr = [];
        for($i=0;$i<$num;$i++){
            $num_arr[] = mt_rand(1,$middle_num)*$step;
        }
        if($order){
            rsort($num_arr);
        }
        return $num_arr;
    }

    public function Sec2Time($time){
        if(is_numeric($time)){
            $value = array(
                "hours" => '00',
                "minutes" => '00',
                "seconds" => '00',
            );
            if($time >= 3600){
                $value["hours"] = sprintf('%02d',floor($time/3600));
                $time = ($time%3600);
            }
            if($time >= 60){
                $value["minutes"] = sprintf('%02d',floor($time/60));
                $time = ($time%60);
            }
            $value["seconds"] = sprintf('%02d',floor($time));
            //return (array) $value;
            $t=$value["hours"] .":". $value["minutes"] .":".$value["seconds"];
            Return $t;

        }else{
            return (bool) FALSE;
        }
    }


    function utf8_strlen($string = null) {
        //将字符串分解为单元
        preg_match_all('/./us', $string, $match);
        //返回单元个数
        return count($match[0]);
    }
    //通过两个时间计算出逾期月数
    public function getM($date1,$date2){
        $timestamp1 = strtotime($date1);
        $timestamp2 = strtotime($date2);
        if ($timestamp1 == $timestamp2)
        {
            return 0;
        }
        if($timestamp1 < 946656000 || $timestamp2 < 946656000){
            return 0;
        }
        if ($timestamp1 > $timestamp2) {
            $small = $timestamp2;
            $big = $timestamp1;
        } else {
            $small = $timestamp1;
            $big = $timestamp2;
        }
        $months = (date("Y",$big)-date("Y",$small))*12 + (date('m', $big) - date('m', $small));
        $months = date('d', $big) >= date('d', $small) ? $months : $months - 1;
        return $months;
    }


}